﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml.Linq;

using Xiaozhou.Utility;


namespace Xiaozhou.Plugins
{
    public class AssemblyLoader
    {

        public AssemblyLoader()
        {
        }

        public MarshalByRefObject LoadAssembly(string assemblyFileName, ref AppDomain pluginDomain)
        {
            string configFileName = Common.getConfigFileName(assemblyFileName);
            MarshalByRefObject instance = null;

            if (File.Exists(configFileName))
            {
                try
                {
                    if (!Common.IsPluginEnabled(configFileName))
                    {
                        return null;
                    }

                    //byte[] assemblyStream = File.ReadAllBytes(assemblyFileName);
                    //Assembly assembly = Assembly.Load(assemblyStream);
                    //Assembly assembly = Assembly.LoadFrom(assemblyFileName);

                    //从配置文件获取类型名称
                    string typeName = Common.GetTypeName(configFileName);

                    pluginDomain = AppDomain.CreateDomain(Common.getFileName(assemblyFileName));
                    
                    if (Common.ExistsConstructParams(configFileName))
                    {
                        //获取参数类型数组
                        Type[] paramTypes = Common.GetParamTypes(configFileName);
                        if (paramTypes == null)
                        {
                            return null;
                        }

                        //获取参数值数组
                        Object[] paramValues = Common.GetParamValues(configFileName);
                        if (paramValues == null)
                        {
                            return null;
                        }

                        if (paramTypes.Length != paramValues.Length)
                        {
                            return null;
                        }

                        //根据类型，转换参数
                        Object[] paramArr = new Object[paramTypes.Length];

                        for (int i = 0; i < paramTypes.Length; i++)
                        {
                            paramArr[i] = Convert.ChangeType(paramValues[i], paramTypes[i]);
                        }

                        instance = pluginDomain.CreateInstanceFromAndUnwrap(
                            assemblyFileName, 
                            typeName, 
                            true, 
                            BindingFlags.CreateInstance, 
                            null, 
                            paramArr, 
                            null, 
                            null, 
                            new System.Security.Policy.Evidence(null)) as MarshalByRefObject;
                    }
                    else
                    {
                        instance = pluginDomain.CreateInstanceFromAndUnwrap(assemblyFileName, typeName) as MarshalByRefObject;
                    }

                }
                catch(Exception ex)
                {
                    string errInfo = ex.Message;
                    return null;
                }
                
            }

            return instance;
        }

        #region old methods
        //private Object GetInstance(Assembly assembly, string typeName)
        //{
        //    return assembly.CreateInstance(typeName) as Object;
        //}

        //private Object GetInstance(Assembly assembly, string typeName, 
        //                           BindingFlags bindingFlags, 
        //                           Object [] constructorParams)
        //{
        //    return assembly.CreateInstance(typeName, false, bindingFlags, null,
        //    constructorParams, null, null) as Object;
        //}
        #endregion

    }
}
